package com.iMusic.businessLogicLayer;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import com.iMusic.businessLogicLayer.orderStatus.OrderStatus;

public class Cart {

	HashMap<Product, Integer> cart = null;
	Account account = null;
	
	static TaxManager taxManager = null;
	
	/*
	 * Constructor
	 */
	public Cart() {
		cart = new HashMap<Product, Integer>();
	}
	

	/*
	 * Creates an Order
	 */
	public Order generateOrder() throws SQLException {
		Order order = new Order(account);
		List <OrderContent> orderContent = new ArrayList<OrderContent>();
		
		for (Product prod : cart.keySet()) {
 			OrderContent oc = new OrderContent(prod.getProductId(), cart.get(prod), prod.getPrice());
 			orderContent.add(oc);
		}
		
		order.setOrderContent(orderContent);
		order.setPaid(false);
		order.setStatus(OrderStatus.InCart);
		order.setTotal(getTotal());
		order.setFederalTaxType(taxManager.getFederalTaxType());
		order.setProvincialTaxType(taxManager.getProvincialTaxType(account.getAddress().getProvince()));
		order.setShippingType((int) ShippingManager.getInstance().getShippingType(account.getAddress().getCountry(), account.getAddress().getProvince()));
		return order;
	}
	
	
	/*
	 * Adds item to cart
	 */
	public void addToCart (Account account, Integer productId, Integer quantity) throws SQLException {

		Integer qtt = 0;
		Set<Product> prodSet = cart.keySet();
		Product prod = null;
		this.account = account;
		
		for (Product p : prodSet) {
			if (p.getProductId().equals(productId)) {
				qtt = cart.get(p);
				prod = p;
				break;
			}
		}

		if (qtt == 0) {
			prod = Product.getProduct(account, productId);
		}

		if (prod.getUnitsInStock() > qtt + quantity) {
			qtt += quantity;
		}
		else if (prod.getTypeName().startsWith("MP3 download")) {
			qtt = 1;
		}

		cart.put(prod, qtt);
	}
	
	
	public void setNewQuantity(Product product, Integer newQtt) {
		if (newQtt == 0) {
			cart.remove(product);
		}
		else if (product.getUnitsInStock() >= newQtt || product.getUnitsInStock() < 0) {
			cart.put(product, newQtt);
		}
	}
	
	/*
	 * Size
	 */
	public int size() {
		
		int size = 0;
		
		Collection<Integer> col = cart.values();
		for (int i : col) {
			size += i;
		}
		
		
		return size;
		
	}


	public Set<Product> getProducts() {
		return cart.keySet();
	}
	

	public Integer getQuantity(Product product) {
		return cart.get(product);
	}
	

	public Float calculateSubtotal() {
		
		float subtotal = 0;
		
		for (Product prod : cart.keySet()) {
			subtotal += Math.floor(prod.getPrice() * cart.get(prod) * 100);
		}
		
		subtotal = subtotal / 100;
		
		return subtotal;
	}

	public Float calculateSubtotal(Product product) {
		
		return (float) Math.floor( product.getPrice() * cart.get(product) * 100) /100;
		
	}

	public float calculateFederalTax() {
		
		if (taxManager == null) {
			taxManager = TaxManager.getInstance();
		}
		
		return taxManager.getFederalTax(calculateSubtotal());
		
	}

	
	public float calculateProvincialTax() {
		
		float tax = 0;
		
		if (taxManager == null) {
			taxManager = TaxManager.getInstance();
		}
		
		
		if (account != null) {
			
			String province = account.getAddress().getProvince();
			
			tax = taxManager.getProvincialTax(province, calculateSubtotal());
		}
		
		return tax;
		
	}


	
	public float getShippingRate() {
		float rate = 0;
	
		if (account != null) {
			
			String province = account.getAddress().getProvince();
			String country = account.getAddress().getCountry();
		
			rate = ShippingManager.getInstance().getShippingRate(country, province);
		}
			
		return rate;
	}
	

	public float getTotal() {
		float total = 0;

		total += calculateSubtotal();
		total += calculateFederalTax();

		if (account != null) {
			String province = account.getAddress().getProvince();
			String country = account.getAddress().getCountry();
			total += ShippingManager.getInstance().getShippingRate(country, province);
			total += calculateProvincialTax();
		}

		
		return (float) (Math.floor(total * 100) / 100);
	}
	
	public Account getAccount() {
		return account;
	}

	public void removeAccount() {
		account = null;
	}


	public void setAccount(Account account) {
		this.account = account;
	}


}
